package entidades;

import util.*;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.google.gson.Gson;
import java.util.LinkedList;

/**
 *
 * @author JFM
 */
public class Uteco extends Entidad
	{
	private String descripcion;
	private int capacidad;
	private boolean interior;
	private boolean barniz;
	private boolean uvTotal;
	private boolean uvSectorizado;
	private int cantidadColores;
	private boolean activo;
	private int paisId;
	
	private Pais pais;
	
	static final String NOMBRE_TABLA = "uteco";




	// --- Constructores --- //

	public Uteco()
		{
		id = 0;
		descripcion = "";
		capacidad = 0;
		interior = false;
		barniz = false;
		uvTotal = false;
		uvSectorizado = false;
		cantidadColores = 0;
		activo = true;
		paisId = 0;
		
		pais = null;
		}

	public Uteco(int id) throws SQLException
		{ super(id); }

	public Uteco(String id) throws SQLException
		{ super(id); }

	public Uteco(ResultSet result) throws SQLException
		{ super(result); }

	public Uteco(ResultSet result, String prefix) throws SQLException
		{ super(result, prefix); }



	// --- Metodos get()/set() --- //

	public boolean isActivo()
		{ return activo; }
	public void setActivo(boolean activo)
		{ this.activo = activo; }
	public void setActivo(String activo)
		{ this.activo = activo != null && ( activo.compareTo("1") == 0 || activo.compareTo("true") == 0); }

	public boolean isInterior()
		{ return interior; }
	public void setInterior(boolean interior)
		{ this.interior = interior; }
	public void setInterior(String interior)
		{ this.interior = interior != null && ( interior.compareTo("1") == 0 || interior.compareTo("true") == 0); }

	public boolean isBarniz()
		{ return barniz; }
	public void setBarniz(boolean barniz)
		{ this.barniz = barniz; }
	public void setBarniz(String barniz)
		{ this.barniz = barniz != null && ( barniz.compareTo("1") == 0 || barniz.compareTo("true") == 0); }

	public boolean isUvTotal()
		{ return uvTotal; }
	public void setUvTotal(boolean uvTotal)
		{ this.uvTotal = uvTotal; }
	public void setUvTotal(String uvTotal)
		{ this.uvTotal = uvTotal != null && ( uvTotal.compareTo("1") == 0 || uvTotal.compareTo("true") == 0); }

	public boolean isUvSectorizado()
		{ return uvSectorizado; }
	public void setUvSectorizado(boolean uvSectorizado)
		{ this.uvSectorizado = uvSectorizado; }
	public void setUvSectorizado(String uvSectorizado)
		{ this.uvSectorizado = uvSectorizado != null && ( uvSectorizado.compareTo("1") == 0 || uvSectorizado.compareTo("true") == 0); }

	public int getCantidadColores()
		{ return cantidadColores; }
	public void setCantidadColores(int cantidadColores)
		{ this.cantidadColores = cantidadColores; }
	public void setCantidadColores(String cantidadColores)
		{ try{ this.cantidadColores = Integer.parseInt(cantidadColores); }catch(Exception e) {}; }

	public int getCapacidad()
		{ return capacidad; }
	public void setCapacidad(int capacidad)
		{ this.capacidad = capacidad; }
	public void setCapacidad(String capacidad)
		{ try{ this.capacidad = Integer.parseInt(capacidad); }catch(Exception e) {}; }

	public String getDescripcion()
		{ return descripcion; }
	public void setDescripcion(String descripcion)
		{ this.descripcion = (descripcion != null)? descripcion : ""; }

	public int getPaisId()
		{ return paisId; }
	public void setPaisId(int paisId)
		{ this.paisId = paisId; }
	public void setPaisId(String paisId)
		{ try{ this.paisId = Integer.parseInt(paisId); }catch(Exception e) {}; }
	public Pais getPais() throws SQLException
		{
		if(pais == null || paisId != pais.getId())
			{ pais = new Pais(paisId); }
		return pais;
		}

	@Override
	public String getDescriptor()
		{ return descripcion; }

	@Override
	public String toString()
		{ return descripcion; }

	@Override
	public String toJson()
		{
		HashMap map = new HashMap();
		map.put("id", id);
		map.put("descripcion", descripcion);
		map.put("capacidad", capacidad);
		map.put("activo", activo);
		map.put("pais_id", paisId);
		return new Gson().toJson(map);
		}

	public boolean puedeImprimir(OrdenTrabajo p) throws SQLException
		{
		boolean res = p.getOrdenVenta().getCantidadColores() + (p.getOrdenVenta().isBarniz()? 1 : 0) <= this.cantidadColores;
		if(p.getOrdenVenta().isInterior()) res = res && this.interior;
		if(p.getOrdenVenta().isBarniz()) res = res && this.barniz;
		if(p.getOrdenVenta().getLacaUvId() == LacaUv.TOTAL) res = res && this.uvTotal;
		if(p.getOrdenVenta().getLacaUvId() == LacaUv.SECTORIZADO) res = res && this.uvSectorizado;
		return res;
		}


	// --- Metodos MySQL --- //

	@Override
	public String getNombreTabla()
		{ return NOMBRE_TABLA; }

	@Override
	public void leer(ResultSet result, String prefijo) throws SQLException
		{
		setId(result.getInt(prefijo + "id"));
		setDescripcion(result.getString(prefijo + "descripcion"));
		setCapacidad(result.getInt(prefijo + "capacidad"));
		setInterior(result.getBoolean(prefijo + "interior"));
		setBarniz(result.getBoolean(prefijo + "barniz"));
		setUvSectorizado(result.getBoolean(prefijo + "uv_sectorizado"));
		setUvTotal(result.getBoolean(prefijo + "uv_total"));
		setCantidadColores(result.getInt(prefijo + "cantidad_colores"));
		setActivo(result.getBoolean(prefijo + "activo"));
		setPaisId(result.getInt(prefijo + "pais_id"));
		}

	@Override
	public void guardar() throws SQLException
		{
		ResultSet result = MySQL.executeQuery("Call Uteco_Save(" +
				MySQL.formatId(id) + "," +
				MySQL.formatId(paisId) + "," +
				MySQL.format(descripcion) + "," +
				MySQL.format(capacidad) + ", " +
				MySQL.formatBit(interior) + ", " +
				MySQL.formatBit(barniz) + ", " +
				MySQL.formatBit(uvTotal) + ", " +
				MySQL.formatBit(uvSectorizado) + ", " +
				MySQL.format(cantidadColores) + ", " +
				MySQL.formatBit(activo) + ")");

		if(result.next())
			{
			if( result.getMetaData().getColumnCount() == 1)
				{
				String msj = result.getString("mensaje");
				throw new SQLException(msj);
				}
			else
				leer(result);
			}

		result.getStatement().close();
		}

	public static void borrar(String id) throws SQLException
		{ MySQL.executeUpdate("Call Uteco_Delete("+id+")"); }

	public static List<Uteco> listar() throws SQLException
		{ return (List) Entidad.listar(Uteco.class, NOMBRE_TABLA, "descripcion ASC"); }

	public static long getCapacidad(int utecoId, Date fechaInicio, Date fechaFin) throws SQLException
		{
		long capacidad = 0;
		ResultSet result = MySQL.executeQuery("SELECT Capacidad_Rango('u',"+utecoId+","+MySQL.format(fechaInicio)+","+MySQL.format(fechaFin)+") AS capacidad");
		if(result.next()) { capacidad = result.getLong("capacidad");}
		result.getStatement().close();
		return capacidad;
		}


	/**
	 * Calcula la fecha en que la Uteco 'utecoId' terminaria de imprimir las bolsas dadas por 'metros' si empieza a trabajar en 'fechaInicio'.
	 *
	 * @param utecoId El id de la Uteco.
	 * @param metros La cantidad de metros que se imprimiran.
	 * @param fechaInicio La fecha de inicio del trabajo.
	 * @return Devuelve la fecha de fin del trabajo de impresion.
	 */
	public static Date calcularFechaFin(int utecoId, Date fechaInicio, long metros) throws SQLException
		{
		Date fechaBloqueado = fechaInicio;
		ResultSet res = MySQL.executeQuery("SELECT FechaImpresion(" + utecoId + ", " + MySQL.format(fechaInicio) + ", " + metros + ") AS fecha");
		if(res.next())
			{ fechaBloqueado = res.getTimestamp("fecha"); }
		res.getStatement().close();
		return fechaBloqueado;
		}

	/**
	 * Calcula la cantidad de pedidos adelantados, al dia y demorados entre 'fecha1' y 'fecha2'.
	 * Una orden esta adelantada, al dia o demorada en funcion de la cantidad de dias que hay entre la fecha de fin de la impresion y la fecha de confeccion:
	 * - Si es menor a Tiempos.diasDeposito, la orden esta atrasada.
	 * - Si es mayor a 2*Tiempos.diasDepotiso, la orden esta adelantada.
	 * - Si es menor a Tiempos.diasDeposito y mayor 2*Tiempos.diasDeposito, la orden esta al día.
	 *
	 * @param fecha1 La fecha de inicio.
	 * @param fecha2 La fecha de fin.
	 * @return Devuelve un array que tiene, en este orden, la cantidad de pedidos adelantados, al dia y atrasados.
	 */
	public long[] getCargaOcupacion(Date fecha1, Date fecha2) throws SQLException
		{
		long res[] = new long[3];

		// Obtengo la suma de la capacidad.
		long capacidadTotal = getCapacidad(this.id, fecha1, fecha2);

		String sentenciaI = "SELECT SUM(metros) AS metrosTotales FROM " + OrdenTrabajoView.VISTA_CON_CICLOS + " WHERE cu_uteco_id = " + this.id + " AND ciclo_uteco_fin >= " + MySQL.formatDateMin(fecha1) + " AND ciclo_uteco_fin < " + MySQL.formatDateMin(fecha2) + " ";
		String sentenciaF = "GROUP BY cu_uteco_id";

		// Obtengo la suma de las cantidades de los pedidos que estan adelantados.
		ResultSet result1 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL 2*TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) <= ciclo_newlong_inicio " + sentenciaF);
		res[0] = (result1.next())? result1.getLong("metrosTotales")*100/capacidadTotal : 0;

		// Obtengo la suma de las cantidades de los pedidos que estan al dia.
		ResultSet result2 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) <= ciclo_newlong_inicio AND DATE_ADD(ciclo_uteco_fin, INTERVAL 2*TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) >= ciclo_newlong_inicio " + sentenciaF);
		res[1] = (result2.next())? result2.getLong("metrosTotales")*100/capacidadTotal : 0;

		// Obtengo la suma de las cantidades de los pedidos que estan atrasados.
		ResultSet result3 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) > ciclo_newlong_inicio " + sentenciaF);
		res[2] = (result3.next())? result3.getLong("metrosTotales")*100/capacidadTotal : 0;

		result1.getStatement().close();
		result2.getStatement().close();
		result3.getStatement().close();
		
		return res;
		}

        public static Uteco getUtecoById(Integer id) throws SQLException{
            LinkedList lista = new LinkedList();
            String query = "SELECT u.* FROM  uteco u  where u.id = " + id;
            ResultSet result = MySQL.executeQuery(query);
            Uteco entidad = new Uteco();
                while(result.next())
		{
			entidad.leer(result);
			lista.add(entidad);
			}
		result.getStatement().close();

		return entidad;
        }

       public Double getCantidadAlDia(Date fecha1, Date fecha2) throws SQLException{
            	long capacidadTotal = getCapacidad(this.id, fecha1, fecha2);
                String sentenciaI = "SELECT SUM(metros) AS metrosTotales FROM " +  OrdenTrabajoView.VISTA_CON_CICLOS + " WHERE cu_uteco_id = " + this.id + " AND ciclo_uteco_fin >= " + MySQL.formatDateMin(fecha1) + " AND ciclo_uteco_fin < " + MySQL.formatDateMin(fecha2) + " ";
		String sentenciaF = "GROUP BY cu_uteco_id";
                ResultSet result1 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL 2*TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) <= ciclo_newlong_inicio " + sentenciaF);
		Double result = (result1.next())? result1.getDouble("metrosTotales")*100/capacidadTotal : 0;

                result1.getStatement().close();

                return result;
        }

        public Double getCantidadAdelantados(Date fecha1, Date fecha2) throws SQLException{
            	long capacidadTotal = getCapacidad(this.id, fecha1, fecha2);
                String sentenciaI = "SELECT SUM(metros) AS metrosTotales FROM " +  OrdenTrabajoView.VISTA_CON_CICLOS + " WHERE cu_uteco_id = " + this.id + " AND ciclo_uteco_fin >= " + MySQL.formatDateMin(fecha1) + " AND ciclo_uteco_fin < " + MySQL.formatDateMin(fecha2) + " ";
		String sentenciaF = "GROUP BY cu_uteco_id";
		ResultSet result2 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) <= ciclo_newlong_inicio AND DATE_ADD(ciclo_uteco_fin, INTERVAL 2*TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) >= ciclo_newlong_inicio " + sentenciaF);
		Double result = (result2.next())? result2.getDouble("metrosTotales")*100/capacidadTotal : 0;
                result2.getStatement().close();

                return result;
        }

        public Double getCantidadDemorado(Date fecha1, Date fecha2) throws SQLException{
            	long capacidadTotal = getCapacidad(this.id, fecha1, fecha2);
                String sentenciaI = "SELECT SUM(metros) AS metrosTotales FROM " +  OrdenTrabajoView.VISTA_CON_CICLOS + " WHERE cu_uteco_id = " + this.id + " AND ciclo_uteco_fin >= " + MySQL.formatDateMin(fecha1) + " AND ciclo_uteco_fin < " + MySQL.formatDateMin(fecha2) + " ";
		String sentenciaF = "GROUP BY cu_uteco_id";
                ResultSet result3 = MySQL.executeQuery(sentenciaI + " AND DATE_ADD(ciclo_uteco_fin, INTERVAL TiemposDeposito_Get(cn_newlong_id, cu_uteco_id) DAY) > ciclo_newlong_inicio " + sentenciaF);
		Double result = (result3.next())? result3.getDouble("metrosTotales")*100/capacidadTotal : 0;
                result3.getStatement().close();

                return result;
        }

}
